package gb;

import gb.oper.PolyOp;
import gb.struct.Monomial;
import gb.struct.Polynomial;

/**
 * 
 * @author uidl7504
 *
 */
public class Reductor {
    
    /**
     * this is with what we reduce
     */
    PolySet internal;

    /**
     * TO BE IMPLEMENTED 
     * @param toReduce
     * @return
     */
    public Polynomial isReducible(Polynomial toReduce) {
        boolean reducible = false;
        Polynomial result = null;
        for(int i = 0; i < internal.size() && !reducible; i++) {
            if (internal.getPoly(i).isDivisible(toReduce) == 1) {
                reducible = true;
                result = internal.getPoly(i);
            }
        }
        return result;
    }
    
    public Polynomial reduce(Polynomial toReduce) {
        Polynomial result = null;
        
        Polynomial temp;
        if ((temp = isReducible(toReduce)) != null) {
        	result = new Polynomial(temp.getComp());
            PolyOp op = internal.getOp();
            Monomial m = Utils.negatePow(Utils.getLM(temp));
            //m = Utils.negateCoef(temp.getMono(0));
           
            //we actually want b * u * f;
            Monomial u = (Monomial) op.multiply(Utils.getLM(toReduce), m);
            double b = toReduce.getMono(0).getCoefficient() / temp.getMono(0).getCoefficient();
            u.setCoefficient(u.getCoefficient() * b);
            
            result = (Polynomial) op.multiply(u, temp);
            for (int i = 0; i < result.size(); i++) {
                result.setMono(Utils.negateCoef(result.getMono(i)), i);
            }
            
            result = (Polynomial) op.add(toReduce, result);
        }
        return result;
    }
    
    public void setSet(PolySet newSet) {
        internal = newSet;
    }
}
